/*
 * @Date: 2022-02-14 14:34:50
 * @LastEditors: 春贰
 * @gitee: https://gitee.com/chun22222222
 * @github: https://github.com/chun222
 * @Desc:
 * @LastEditTime: 2022-09-05 11:00:45
 * @FilePath: \server\system\core\db\db.go
 */
package db

import (
	"fmt"
	"os"

	"time"

	"go2admin_pure/system/core/config"
	"go2admin_pure/system/core/log"
	"go2admin_pure/system/model/DbModel"
	"go2admin_pure/system/util/file"
	"go2admin_pure/system/util/sys"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/schema"
)

var conn *gorm.DB

var basedir = sys.ExecutePath() + "\\" //根目录

func Instance() *gorm.DB {
	if conn == nil {
		InitConn()
	}
	return conn
}

func InitConn() {
	switch config.Instance().DB.DBType {
	//后期拓展别的数据库
	case "mysql":
		conn = GormMysql()
	default:
		log.Write(log.Fatal, "No DBType")
	}
}

var err error

func GormMysql() *gorm.DB {
	m := config.Instance().DB
	if m.DBName == "" {
		return nil
	}

	dsn := m.DBUser + ":" + m.DBPwd + "@tcp(" + m.DBHost + ")/" //

	conn, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})

	if err != nil {
		fmt.Println("run mysql error1", err.Error())
		os.Exit(0)
	}
	conn.Exec("CREATE DATABASE  IF NOT EXISTS `" + m.DBName + "`") //先创建
	dsn = m.DBUser + ":" + m.DBPwd + "@tcp(" + m.DBHost + ")/" + m.DBName + "?charset=utf8mb4&parseTime=True&loc=Local"

	conn, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger:      LogConfig(),
		PrepareStmt: true,
		NamingStrategy: schema.NamingStrategy{
			//TablePrefix:   "t_",                              // 表前缀
			SingularTable: true, // 不添加后缀s
			//NoLowerCase:   true, // 取消驼峰
		},
	})
	if err != nil {
		fmt.Println("run mysql error2", err.Error())
		os.Exit(0)
	}
	sqlDB, _ := conn.DB()
	sqlDB.SetMaxIdleConns(100)
	sqlDB.SetMaxOpenConns(300)
	//设置事务隔离级别
	conn.Exec("SET global TRANSACTION ISOLATION LEVEL READ COMMITTED")
	initTables()
	return conn
}

//初始化表
func initTables() {
	CheckTableData(
		&DbModel.SysUser{},
		&DbModel.SysRole{},
		&DbModel.SysUserRole{},
		&DbModel.SysPermission{},
		&DbModel.SysRolePermission{},
		&DbModel.SysUserPermission{},
		&DbModel.SysRecord{},
		&DbModel.SysConfig{},
		&DbModel.SysSequence{},
	)

	if file.CheckNotExist(basedir + "install_lock") {
		initData()
		os.Create(basedir + "install_lock")
	}

}
func CheckTableData(tbs ...interface{}) {
	for _, tb := range tbs {
		if !conn.Migrator().HasTable(tb) {
			if err := conn.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4").Migrator().CreateTable(tb); err != nil {
				log.Write(log.Fatal, "init database error: "+err.Error())
			}
		} else {
			//关闭自动加字段
			// if err := conn.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8").AutoMigrate(tb); err != nil {
			// 	log.Write(log.Fatal, "init database error: "+err.Error())
			// }

		}
	}
}

//原生查询返回结果到map
func QueryMap(sql string) ([]map[string]interface{}, error) {
	rows, _ := Instance().Raw(sql).Rows()
	cols, _ := rows.Columns()
	types, _ := rows.ColumnTypes()

	var r []map[string]interface{}
	for rows.Next() {
		m := make(map[string]interface{})
		columns := make([]interface{}, len(cols))
		columnPointers := make([]interface{}, len(cols))
		for i, _ := range columns {
			columnPointers[i] = &columns[i]
		}

		if err := rows.Scan(columnPointers...); err != nil {
			return nil, err
		}

		for i, colName := range cols {
			//这里类型有很多 不细处理  插入反正没问题
			//gorm真难用
			if types[i].DatabaseTypeName() == "DATETIME" {
				val := columnPointers[i].(*interface{})
				if *val != nil {
					m[colName] = (*val).(time.Time).Format("2006-01-02 15:04:05")
				} else {
					m[colName] = *val
				}
			} else {
				val := columnPointers[i].(*interface{})
				m[colName] = *val
			}

		}
		r = append(r, m)
	}
	return r, nil
}

//读取sql 初始化
func initData() {
	sqlfile := basedir + "databackup\\init.sql"
	if !file.CheckNotExist(sqlfile) {
		Import(sqlfile)
	}
}
